﻿namespace HuwmanCode.UserAccountControl

open System
open System.Diagnostics
open System.Runtime.InteropServices

type public ProcessElevation =
    | Unsupported = 0 //Only supported on Vista and above
    | Default = 1     //UAC is probably turned off
    | Elevated = 2    //The process is elevated
    | Limited = 3     //The process is unelevated

type public Uac =
    /// <summary>
    /// The UAC (User Account Control) process elevation
    /// </summary
    static member ProcessElevation
        with get() =
            if Environment.OSVersion.Version.Major < 6 then ProcessElevation.Unsupported
            else
                let mutable tokenHandle = IntPtr.Zero
                let procHandle = Process.GetCurrentProcess().Handle
                match OpenProcessToken(procHandle, TokenDesiredAccess.Query, &tokenHandle) with
                | false -> ProcessElevation.Unsupported
                | true -> 
                    let intTypeSize = Marshal.SizeOf(typeof<int>)
                    let tokenElevationTypeBuffer = Marshal.AllocHGlobal(intTypeSize)
                    try
                        let mutable returnLength = 0
                        let success = NativeMethods.GetTokenInformation(tokenHandle, TokenInformationType.TokenElevationType,
                                        tokenElevationTypeBuffer, intTypeSize, &returnLength)
                        match success with
                        | true when returnLength = intTypeSize -> enum(Marshal.ReadInt32(tokenElevationTypeBuffer))
                        | _ -> ProcessElevation.Default
                    finally
                        Marshal.FreeHGlobal(tokenElevationTypeBuffer)                    
                        NativeMethods.CloseHandle(tokenHandle) |> ignore

